use crate::models::{Book, Books, BorrowItem, SearchParams};
// use crate::templates::SearchTemplate; // 稍后定义这个模板结构体

use crate::templates::*;

use axum::{
    extract::{Form, Query, State},
    response::{IntoResponse, Redirect},
};
// 删除 use axum_extra::extract::CookieJar;引用, 实际建议用 tower-sessions
use chrono::Local; // 删除 Duration 引用
use serde::Deserialize;
use sqlx::{Pool, Postgres};
use tower_sessions::Session;

// --- 图书添加表单 ---
#[derive(Deserialize)]
pub struct AddBookForm {
    book_name: String,
    author: String,
    copies: i32,
    synopsis: String,
}

// --- 借阅/归还/修复 操作表单 ---
#[derive(Deserialize)]
pub struct ActionForm {
    item_id: i32,
    action: String, // "borrow", "return", "repair"
}

// 首页 & 列表
pub async fn index_handler(
    State(pool): State<Pool<Postgres>>,
    session: Session,
) -> impl IntoResponse {
    // 简单鉴权检查
    let user_id: Option<i32> = session.get("user_id").await.unwrap_or(None);
    if user_id.is_none() {
        return Redirect::to("/login").into_response();
    }
    let username: String = session
        .get("username")
        .await
        .unwrap_or(Some("User".to_string()))
        .unwrap();

    // 获取图书
    let books = sqlx::query_as::<_, Book>("SELECT * FROM books ORDER BY id DESC")
        .fetch_all(&pool)
        .await
        .unwrap_or_default();

    // 获取借阅/副本详情 (联表查询)
    let items = sqlx::query_as::<_, BorrowItem>(
        r#"
        SELECT b.id, b.book_id, k.book_name, b.librarian, b.borrow_datetime,
               b.return_datetime, b.book_state, b.book_preserve
        FROM borrows b
        JOIN books k ON b.book_id = k.id
        ORDER BY b.id DESC
        "#,
    )
    .fetch_all(&pool)
    .await
    .unwrap_or_default();

    IndexTemplate {
        username,
        books,
        items,
        message: None,
    }
    .into_response()
}

// 图书查询 GET /search
pub async fn search_page(
    State(pool): State<Pool<Postgres>>,
    session: Session,
    Query(params): Query<SearchParams>,
) -> impl IntoResponse {
    // 1. 【关键】从 Session 中提取当前登录用户
    // (如果你希望访客也能看，可以注释掉这块，给 username 默认值)
    let user_id: Option<i32> = session.get("user_id").await.unwrap_or(None);
    let username: String = if user_id.is_some() {
        session
            .get("username")
            .await
            .unwrap_or(Some("User".to_string()))
            .unwrap()
    } else {
        "访客".to_string()
    };

    // 1. 获取当前登录用户信息
    // let mut username = "访客".to_string();
    // let user_id: Option<i32> = session.get("user_id").await.unwrap_or(None);
    // if user_id.is_some() {
    //     // return Redirect::to("/login").into_response();
    //     let mut username: String = session
    //         .get("username")
    //         .await
    //         .unwrap_or(Some("User".to_string()))
    //         .unwrap();
    // }

    // 2. 处理搜索关键词
    let keyword = params.q.unwrap_or_default();
    let search_pattern = format!("%{}%", keyword); // 加上 % 用于模糊匹配

    // 3. 执行查询 SQL (重点在 ORDER BY)
    // 逻辑：CASE WHEN status = '借出' THEN 0 ELSE 1 END
    // 这样 '借出' 对应 0，'馆藏' 对应 1，升序排列时 0 在前。
    let sql = r#"
        SELECT b.id, b.book_name, b.author, b.number_of_copies, k.book_state
        FROM books b
        JOIN borrows k ON b.id = k.book_id
        WHERE b.book_name ILIKE $1
        ORDER BY
            CASE WHEN k.book_state = '已借' THEN 0 ELSE 1 END ASC,
            id DESC
    "#;

    let books = sqlx::query_as::<_, Books>(sql)
        .bind(search_pattern)
        .fetch_all(&pool)
        .await
        .unwrap_or_else(|e| {
            println!("搜索查询失败: {:?}", e);
            vec![]
        });

    // 4. 返回模板
    // 假设你使用的是 Askama，如果不使用 Askama 请相应调整
    SearchTemplate {
        username,
        keyword,
        books,
    }
}

// 添加图书 (事务处理 + 自动生成副本)
pub async fn add_book_handler(
    State(pool): State<Pool<Postgres>>,
    session: Session,
    Form(form): Form<AddBookForm>,
) -> impl IntoResponse {
    let user_id: i32 = session.get("user_id").await.unwrap().unwrap();
    let username: String = session.get("username").await.unwrap().unwrap();

    let mut tx = pool.begin().await.unwrap();

    // 1. 插入 Books 表
    let book_id: i32 = sqlx::query_scalar(
        r#"INSERT INTO books (user_id, book_name, author, number_of_copies, synopsis, cataloguer)
           VALUES ($1, $2, $3, $4, $5, $6) RETURNING id"#,
    )
    .bind(user_id)
    .bind(&form.book_name)
    .bind(&form.author)
    .bind(form.copies)
    .bind(&form.synopsis)
    .bind(&username) // 登记员
    .fetch_one(&mut *tx)
    .await
    .unwrap();

    // 2. 根据副本数自动生成 Borrows 记录
    for _ in 0..form.copies {
        sqlx::query(
            "INSERT INTO borrows (book_id, book_state, book_preserve) VALUES ($1, '馆藏', 0)",
        )
        .bind(book_id)
        .execute(&mut *tx)
        .await
        .unwrap();
    }

    tx.commit().await.unwrap();

    // HTMX 重定向回首页 (或者返回局部 HTML)
    Redirect::to("/")
}

// 处理借阅/归还/修复 (核心逻辑)
pub async fn book_action_handler(
    State(pool): State<Pool<Postgres>>,
    session: Session,
    Form(form): Form<ActionForm>,
) -> impl IntoResponse {
    let username: String = session
        .get("username")
        .await
        .unwrap()
        .unwrap_or("Admin".to_string());
    let mut message = None;

    // 获取当前状态
    let item = sqlx::query_as::<_, BorrowItem>(
        "SELECT b.*, k.book_name FROM borrows b JOIN books k ON b.book_id = k.id WHERE b.id = $1",
    )
    .bind(form.item_id)
    .fetch_one(&pool)
    .await
    .unwrap();

    match form.action.as_str() {
        "borrow" => {
            if item.book_state == "馆藏" {
                sqlx::query(
                    "UPDATE borrows SET book_state = '已借', borrow_datetime = $1, librarian = $2 WHERE id = $3"
                )
                .bind(Local::now().naive_local())
                .bind(username)
                .bind(form.item_id)
                .execute(&pool).await.unwrap();
            }
        }
        "return" => {
            if item.book_state == "已借" {
                let now = Local::now().naive_local();
                let borrow_time = item.borrow_datetime.unwrap_or(now);
                let days_diff = (now - borrow_time).num_days();

                // 罚款计算：超期1天罚1分钱
                let fine = if days_diff > 30 {
                    let overdue_days = days_diff - 30;
                    format!(
                        "超期 {} 天，罚款: {:.2} 元",
                        overdue_days,
                        (overdue_days as f64) * 0.01
                    )
                } else {
                    "归还成功，未超期".to_string()
                };
                message = Some(fine);

                sqlx::query(
                    "UPDATE borrows SET book_state = '馆藏', return_datetime = $1 WHERE id = $2",
                )
                .bind(now)
                .bind(form.item_id)
                .execute(&pool)
                .await
                .unwrap();
            }
        }
        "repair" => {
            let new_state = if item.book_state == "修复" {
                "馆藏"
            } else {
                "修复"
            };
            let preserve_inc = if new_state == "修复" { 0 } else { 1 }; // 修复完成时次数+1

            sqlx::query(
                "UPDATE borrows SET book_state = $1, book_preserve = book_preserve + $2 WHERE id = $3"
            )
            .bind(new_state)
            .bind(preserve_inc)
            .bind(form.item_id)
            .execute(&pool).await.unwrap();
        }
        _ => {}
    }

    // 重新查询列表返回局部 HTML 给 HTMX 更新
    let items = sqlx::query_as::<_, BorrowItem>(
        r#"SELECT b.id, b.book_id, k.book_name, b.librarian, b.borrow_datetime,
           b.return_datetime, b.book_state, b.book_preserve
           FROM borrows b JOIN books k ON b.book_id = k.id ORDER BY b.id DESC"#,
    )
    .fetch_all(&pool)
    .await
    .unwrap_or_default();

    ItemsTableTemplate { items, message }
}
